﻿#pragma once
/* 
* COPYRIGHT 2012 Mafahir Fairoze
* 
* This file is part of Vector Template Library (Vtl) v1.0.
* (Project Website : http://mafahir.wordpress.com/projects/neuralplusplus)
* 
* Vector Template Library (Vtl) v1.0 is a free software. You can redistribute it and/or modify it under the terms of
* the GNU General Public License as published by the Free Software Foundation, either version 3
* of the License, or (at your option) any later version.
* 
* Vector Template Library (Vtl) v1.0 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License <http://www.gnu.org/licenses/> for more details.
*/

#ifndef _CRT_RAND_S
#define _CRT_RAND_S
#endif

#include <stdlib.h>
#include "Vtl/eigen.h"

namespace Vtl
{
	namespace common
	{
		/*!
		*  \brief Returns the 2D euclidean distance between two points along the [i,j] plane.
		*  \param[in] _P0 
		*  \param[in] _P1 
		*  \return Scalar 
		*/
		template<typename Scalar, int Dimension>
		inline Scalar distance2D( const Eigen::Matrix<Scalar,Dimension,1> &_P0, 
			const Eigen::Matrix<Scalar,Dimension,1> &_P1);

		/*!
		*  \brief Returns the 2D euclidean squared distance between two points along the [i,j] plane.
		*  \param[in] _P0 
		*  \param[in] _P1 
		*  \return Scalar 
		*/
		template<typename Scalar, int Dimension>
		inline Scalar sqDistance2D( const Eigen::Matrix<Scalar,Dimension,1> &_P0, 
			const Eigen::Matrix<Scalar,Dimension,1> &_P1);

		/*!
		*  \brief Returns the euclidean distance between two points.
		*  \param[in] _P0 
		*  \param[in] _P1 
		*  \return Scalar 
		*/
		template<typename Scalar, int Dimension>
		inline Scalar distance( const Eigen::Matrix<Scalar,Dimension,1> &_P0, 
			const Eigen::Matrix<Scalar,Dimension,1> &_P1);

		/*!
		*  \brief Returns the euclidean squared distance between two points.
		*  \param[in] _P0 
		*  \param[in] _P1 
		*  \return Scalar 
		*/
		template<typename Scalar, int Dimension>
		inline Scalar sqDistance( const Eigen::Matrix<Scalar,Dimension,1> &_P0, 
			const Eigen::Matrix<Scalar,Dimension,1> &_P1);

		/*!
		*  \brief Converts the given vector to 2D [i,j] only.
		*  \param[in] _Matrix 
		*  \return Eigen::Matrix<Scalar, 2,1>
		*/
		template <typename Scalar, int Dimension>
		inline Eigen::Matrix<Scalar, 2,1> convertTo2D(const Eigen::Matrix<Scalar, Dimension,1> &_Matrix);

		/*!
		*  \brief Converts the given line to 2D [i,j] only.
		*  \param[in] _Line 
		*  \return Eigen::ParametrizedLine<Scalar, 2>
		*/
		template <typename Scalar, int Dimension>
		inline Eigen::ParametrizedLine<Scalar, 2> convertTo2D(const Eigen::ParametrizedLine<Scalar, Dimension> &_Line);

		/*!
		*  \brief Converts the given vector to 3D using the given K value for [i,j, K].
		*  \note If a vector with a dimension 3 or above is given it will ignore the user given value for K and use existing.
		*  \param[in] _Matrix 
		*  \param[in] _K 
		*  \return Eigen::Matrix<Scalar, 3,1>
		*/
		template <typename Scalar, int Dimension>
		inline Eigen::Matrix<Scalar, 3,1> convertTo3D(const Eigen::Matrix<Scalar, Dimension,1> &_Matrix, const Scalar &_K = 0.0);

		/*!
		*  \brief Converts the given line to 3D using the given K value for [i,j, K].
		*  \note If a line with a dimension 3 or above is given it will ignore the user given value for K and use existing
		*  \param[in] _Line 
		*  \param[in] _K 
		*  \return Eigen::ParametrizedLine<Scalar, 3>
		*/
		template <typename Scalar, int Dimension>
		inline Eigen::ParametrizedLine<Scalar, 3> convertTo3D(const Eigen::ParametrizedLine<Scalar, Dimension> &_Line, const Scalar &_K = 0.0);

		/*!
		*  \brief Generates uniformly distributed pseudo-random number.
		*  \return Scalar return value is [0 ≤ value < 1]
		*/
		template <typename Scalar>
		inline Scalar random();

		/*!
		*  \brief Generates uniformly distributed pseudo-random number between the given range.
		*  \param[in] _MinValue the minimum random number value. [min ≤ value]
		*  \param[in] _MaxValue the maximum random number value. [value ≤ max]
		*  \return Scalar 
		*/
		template <typename Scalar>
		inline Scalar rangedRandom(const Scalar &_MinValue = Scalar(-1), const Scalar &_MaxValue = Scalar(1));

		/*!
		*  \brief Generates uniformly distributed pseudo-random vector within the distribution radius given.
		*  \param[in] _Scale the distribution radius.
		*  \return Eigen::Matrix<Scalar, Dimension, 1>
		*/
		template <typename Scalar, int Dimension>
		inline Eigen::Matrix<Scalar, Dimension, 1> randomVector(const Scalar &_Scale = Scalar(1));
	};
};

#include "Vtl/impl/common.hpp"